package com.syni.mdd.yhd.common.all.service.impl;

import com.syni.mdd.sjb.common.component.utils.common.utils.DateTimeUtils;
import com.syni.mdd.sjb.common.component.utils.common.utils.ParamsMap;
import com.syni.mdd.sjb.common.component.utils.common.utils.ResultMapHelper;
import com.syni.mdd.yhd.common.all.constants.Constants;
import com.syni.mdd.yhd.common.all.constants.ResultCode;
import com.syni.mdd.yhd.common.all.constants.ResultMsg;
import com.syni.mdd.yhd.common.all.dao.jpa.BmsFullCouponDao;
import com.syni.mdd.yhd.common.all.entity.BmsBusiness;
import com.syni.mdd.yhd.common.all.entity.BmsDxClientRole;
import com.syni.mdd.yhd.common.all.entity.coupon.BmsFullCoupon;
import com.syni.mdd.yhd.common.all.entity.coupon.BmsUserReceCoupon;
import com.syni.mdd.yhd.common.all.service.BmsBusinessService;
import com.syni.mdd.yhd.common.all.service.BmsDxClientRoleService;
import com.syni.mdd.yhd.common.all.service.BmsFullCouponService;
import com.syni.mdd.yhd.common.all.service.BmsUserReceCouponService;
import com.syni.mdd.yhd.common.all.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @className
 * @description TOO
 * @Author cfx
 * @DATE 2019/4/9 12:04
 * @VERSION 1.0
 **/
@Service
public class BmsFullCouponServiceImpl extends BaseService<BmsFullCoupon, Integer> implements BmsFullCouponService {

    @Value("${full.copuon.druing.time:2019-09-28,2019-10-07}")
    private String duringTime;

    @Autowired
    BmsFullCouponDao bmsFullCouponDao;

    @Autowired
    BmsBusinessService bmsBusinessService;

    @Autowired
    BmsUserReceCouponService bmsUserReceCouponService;

    @Autowired
    BmsDxClientRoleService bmsDxClientRoleService;

    @Autowired
    RedisTemplate redisTemplate;
    @Override
    public BmsFullCouponDao getBaseDao() {
        return bmsFullCouponDao;
    }

    @Override
    public Map<String, Object> openFullCopuon(ParamsMap paramsMap) {
        if(redisTemplate.hasKey(Constants.REDIS_KEY_FULL_COUPON_OPEN)){
            String activityTime = redisTemplate.opsForValue().get(Constants.REDIS_KEY_FULL_COUPON_OPEN).toString();
            String[] startEndTime = activityTime.split(",");
            Integer startTime = DateTimeUtils.converDateToInterger(DateTimeUtils.converStringToDate(startEndTime[0],DateTimeUtils.DATE_PATTERN_DAY_07));
            Integer endTime = DateTimeUtils.converDateToInterger(DateTimeUtils.addDay(DateTimeUtils.converStringToDate(startEndTime[1],DateTimeUtils.DATE_PATTERN_DAY_07),1));
            Integer nowTime = DateTimeUtils.getNowTimeStamp();
            if(nowTime >= startTime && nowTime < endTime) {
                Map<String, Object> resultMap = new HashMap<>();
                resultMap.put("startTime", startEndTime[0]);
                resultMap.put("endTime", startEndTime[1]);
                return ResultMapHelper.success(resultMap, "ok");
            }
        }
        return ResultMapHelper.result(ResultCode.CODE_ERROR,"no activity");
    }

    @Override
    public Map<String, Object> getBusinessFullCoupon(ParamsMap paramsMap) {
        Map<String,Object> resultMap = new HashMap<>();
        Integer businessId = paramsMap.getInteger("businessId");
        Integer pageSize = paramsMap.getInteger("pageSize");
        String activityId = paramsMap.getString("activityId");
        List<BmsFullCoupon> bmsFullCoupons = new LinkedList<>();
        //找出推荐满减券
        resultMap.putAll(getNearBusinessFullCoupon(bmsFullCoupons,businessId,activityId,pageSize,paramsMap));
        bmsFullCoupons = (List<BmsFullCoupon>) resultMap.get("fullCoupons");
        if(bmsFullCoupons.size() > 0){
            Set<Integer> businessIds = new HashSet<>();
            for(BmsFullCoupon bmsFullCoupon : bmsFullCoupons){
                businessIds.add(bmsFullCoupon.getBusinessId());
            }
            Map<Integer, BmsBusiness> bmsBusinessMap = bmsBusinessService.findBusinessByIds(businessIds);
            for(BmsFullCoupon bmsFullCoupon : bmsFullCoupons){
                if(bmsBusinessMap.containsKey(bmsFullCoupon.getBusinessId())){
                    bmsFullCoupon.setBmsBusiness(bmsBusinessMap.get(bmsFullCoupon.getBusinessId()));
                }
            }
        }
        resultMap.put("fullCoupons",bmsFullCoupons);
        return ResultMapHelper.success(resultMap, ResultMsg.MSG_GET_SUCCESS);
    }

    public Map<String,Object> getNearBusinessFullCoupon(List<BmsFullCoupon> resultTrueFullCoupon,
                                                        Integer businessId,String activityId,Integer num,ParamsMap paramsMap){
        //附近信息
        Map<String,Object> resultMap = new HashMap<>();
        String addrCity = paramsMap.getString("addrCity");
        String addrDistrict = paramsMap.getString("addrDistrict");
        String latitude = paramsMap.getString("latitude");
        String longitude = paramsMap.getString("longitude");
        if(activityId == null){
            activityId = UUID.randomUUID().toString().replaceAll("-", "");
            getFullCouponOver(resultTrueFullCoupon,businessId,
                    addrCity,addrDistrict,latitude,longitude,num,activityId);
        }else {
            String redisKey = Constants.REDIS_KEY_FULL_COUPON + activityId;
            if(redisTemplate.hasKey(redisKey)){
                //拉出多少个
                for(int ii = 0;ii < num;ii++) {
                    BmsFullCoupon bmsFullCoupon = (BmsFullCoupon) redisTemplate.opsForList().rightPopAndLeftPush(redisKey, redisKey);
                    resultTrueFullCoupon.add(bmsFullCoupon);
                }
            }else {
                activityId = UUID.randomUUID().toString().replaceAll("-", "");
                getFullCouponOver(resultTrueFullCoupon,businessId,addrCity,
                        addrDistrict,latitude,longitude,num - resultTrueFullCoupon.size(),activityId);
            }
        }
        resultMap.put("fullCoupons",resultTrueFullCoupon);
        resultMap.put("activityId",activityId);
        return resultMap;
    }

    /**
     * @Description 重新获取统计
     * @Author: cfx
     * @Date: 2019/9/17
     */
    public List<BmsFullCoupon> getFullCouponOver(List<BmsFullCoupon> resultTrueFullCoupon,
                                                 Integer businessId,String addrCity,String addrDistrict,
                                                 String latitude,String longitude,Integer num,String activityId){
        List<BmsFullCoupon> resultBmsFullCoupon = new ArrayList<>();
        Map<String,Object> conditionMap = new HashMap<>();
        if(businessId != null) {
            List<BmsFullCoupon> bmsFullCouponList = bmsFullCouponDao.findByBusinessIdAndIsDisplay(businessId,Constants.COMMON_FLAG_FALSE_INT);
            if(bmsFullCouponList != null && bmsFullCouponList.size() > 0){
                resultTrueFullCoupon.add(bmsFullCouponList.get(0));
            }
            Set<Integer> businessIds = new HashSet<>();
            businessIds.add(businessId);
            conditionMap.put("businessId_NIN", businessIds);
        }
        conditionMap.put("isDisplay",Constants.COMMON_FLAG_FALSE_INT);
        List<BmsFullCoupon> bmsFullCoupons = bmsFullCouponDao.findAll(new SpecificationUtils(conditionMap));
        //查出来的businessId的位置
        Map<Integer,BmsFullCoupon> bmsFullCouponMap = new HashMap<>();
        if(bmsFullCoupons != null && bmsFullCoupons.size() > 0){
            Set<Integer> buinessIds = new HashSet<>();
            for(BmsFullCoupon bmsFullCoupon : bmsFullCoupons){
                bmsFullCouponMap.put(bmsFullCoupon.getBusinessId(),bmsFullCoupon);
                buinessIds.add(bmsFullCoupon.getBusinessId());
            }
            if(StringUtils.isNotBlank(latitude) && StringUtils.isNotBlank(longitude)
                    && StringUtils.isNotBlank(addrCity) && StringUtils.isNotBlank(addrDistrict)) {
                //有定位
                List<Map<String,Object>> businessList = bmsBusinessService.findBusinessByLocation(addrCity,addrDistrict,buinessIds);
                if(businessList != null && businessList.size() > 0) {
                    String[] selfDistances = {"3","5","10","20"};
                    End:for (String dis : selfDistances) {
                        double selfDis = Double.parseDouble(dis) * 1000;
                        for (Map<String, Object> business : businessList) {
                            if (business.containsKey("latitude") && StringUtils.checkNullAndEmpty(business.get("latitude"))
                                    && business.containsKey("longitude") && StringUtils.checkNullAndEmpty(business.get("longitude"))) {
                                double lat = Double.parseDouble(business.get("latitude").toString());
                                double lnt = Double.parseDouble(business.get("longitude").toString());
                                double distance = LocationUtils.getDistance(lat, lnt, Double.parseDouble(latitude), Double.parseDouble(longitude));
                                //公里数以内
                                if (distance < selfDis) {
                                    //取出那个券
                                    Integer id = Integer.parseInt(business.get("id").toString());
                                    if(bmsFullCouponMap.containsKey(id)){
                                        BmsFullCoupon bmsFullCoupon = bmsFullCouponMap.get(id);
                                        resultBmsFullCoupon.add(bmsFullCoupon);
                                        bmsFullCouponMap.remove(id);
                                    }
                                }
                            }
                        }
                    }
                }
                if(resultBmsFullCoupon.size() < num){
                    Integer count = num - resultBmsFullCoupon.size();
                    if(bmsFullCoupons.size() > 0) {
                        for (int ii = 0; ii < count; ii++) {
                            int random = (int)(Math.random() * bmsFullCoupons.size());
                            resultBmsFullCoupon.add(bmsFullCoupons.get(random));
                            bmsFullCoupons.remove(random);
                        }
                    }
                }
            }else {
                //没定位推荐固定商家
                resultBmsFullCoupon.addAll(bmsFullCoupons);
            }
            if(resultBmsFullCoupon.size() > 0){
                //拉出多少个
                resultTrueFullCoupon.addAll(resultBmsFullCoupon.subList(0,num - resultTrueFullCoupon.size()));
                resultBmsFullCoupon.removeAll(resultTrueFullCoupon);
                if(resultBmsFullCoupon.size() > 0){
                    String redisKey = Constants.REDIS_KEY_FULL_COUPON + activityId;
                    redisTemplate.opsForList().leftPushAll(redisKey, resultBmsFullCoupon);
                    redisTemplate.expire(redisKey, 1, TimeUnit.HOURS);
                    redisTemplate.opsForList().leftPushAll(redisKey,resultTrueFullCoupon);
                }
            }
        }
        return resultTrueFullCoupon;
    }

    @Override
    public Map<String, Object> checkUserIsReceive(ParamsMap paramsMap) {
        Integer userId = paramsMap.getInteger("userIdentify");
        List<BmsUserReceCoupon> bmsUserReceCoupons = bmsUserReceCouponService.getBaseDao().findByUserIdAndType(userId,Constants.USER_RECE_FULL_COUPON);
        if(bmsUserReceCoupons != null && bmsUserReceCoupons.size() >= Constants.MAX_FULL_COUPON_GET){
            Set<Integer> businessIds = bmsUserReceCoupons.stream().map(BmsUserReceCoupon::getBusinessId).collect(Collectors.toSet());
            Map<Integer,BmsBusiness> bmsBusinessMap = bmsBusinessService.findBusinessByIds(businessIds);
            for(BmsUserReceCoupon bmsUserReceCoupon : bmsUserReceCoupons) {
                if(bmsBusinessMap.containsKey(bmsUserReceCoupon.getBusinessId())){
                    bmsUserReceCoupon.getBmsFullCoupon().setBmsBusiness(bmsBusinessMap.get(bmsUserReceCoupon.getBusinessId()));
                }
                bmsUserReceCoupon.getBmsFullCoupon().setEndTime(bmsUserReceCoupon.getExpireTime());
            }
            return ResultMapHelper.result(ResultCode.CODE_USER_ALREADY_GET_COUPON_MAX,ResultMsg.CODE_USER_ALREADY_GET_COUPON_MAX,bmsUserReceCoupons);
        }
        return ResultMapHelper.success(null,"ok");
    }

    /**
     * @Description 领取店铺的优惠券
     * @Author: cfx
     * @Date: 2019/9/18
     */
    @Override
    public Map<String, Object> userReceiveFullCoupon(ParamsMap paramsMap) {
        Integer fullCouponId = paramsMap.getInteger("id");
        Integer businessId = paramsMap.getInteger("businessId");
        Integer userId = paramsMap.getInteger("userIdentify");
        Optional<BmsBusiness> bmsBusinessOptional = bmsBusinessService.getBaseDao().findById(businessId);
        if(!bmsBusinessOptional.isPresent()){
            return ResultMapHelper.result(ResultCode.CODE_BUSINESS_NO_EXIST,ResultMsg.CODE_BUSINESS_NO_EXIST);
        }
        Optional<BmsFullCoupon> bmsFullCouponOptional = bmsFullCouponDao.findById(fullCouponId);
        if(!bmsFullCouponOptional.isPresent()){
            return ResultMapHelper.result(ResultCode.CODE_FULL_COUPON_IS_NO_EXIST,ResultMsg.CODE_FULL_COUPON_IS_NO_EXIST);
        }
        BmsFullCoupon bmsFullCoupon = bmsFullCouponOptional.get();
        if(bmsFullCoupon.getBusinessId().intValue() != businessId.intValue()){
            return ResultMapHelper.result(ResultCode.CODE_FULL_COUPON_IS_NO_BELONG,ResultMsg.CODE_FULL_COUPON_IS_NO_BELONG);
        }
        //判断是否是活动期间注册
        if(!redisTemplate.hasKey(Constants.REDIS_KEY_FULL_COUPON_OPEN)){
            return ResultMapHelper.result(ResultCode.CODE_ERROR,"no activity");
        }
        String[] duringTimes = redisTemplate.opsForValue().get(Constants.REDIS_KEY_FULL_COUPON_OPEN).toString().split(",");
        Integer startTime = DateTimeUtils.converDateToInterger(DateTimeUtils.converStringToDate(duringTimes[0],DateTimeUtils.DATE_PATTERN_DAY_07));
        Integer endTime = DateTimeUtils.converDateToInterger(DateTimeUtils.addDay(DateTimeUtils.converStringToDate(duringTimes[1],DateTimeUtils.DATE_PATTERN_DAY_07),1));
        //查询角色创建时间
        List<BmsDxClientRole> bmsDxClientRoles = bmsDxClientRoleService.getUserClienRole(userId,Constants.GENERAL_USER_ROLE_ID);
        if(!(bmsDxClientRoles != null && bmsDxClientRoles.size() > 0)){
            bmsDxClientRoles = new ArrayList<>();
            Map<String,Object> resultMap = bmsDxClientRoleService.addRegisterUserRole(userId,Constants.GENERAL_USER_ROLE_ID);
            BmsDxClientRole bmsDxClientRole = (BmsDxClientRole) resultMap.get("data");
            bmsDxClientRoles.add(bmsDxClientRole);
        }
        Integer registerTime = (int)(bmsDxClientRoles.get(0).getNewTime().getTime() / 1000);
        System.out.println(startTime);
        System.out.println(endTime);
        if(!(registerTime >= startTime && registerTime < endTime)){
            return ResultMapHelper.result(ResultCode.CODE_USER_NO_REGISTER_IN_ACT,ResultMsg.CODE_USER_NO_REGISTER_IN_ACT);
        }
        BmsBusiness business = bmsBusinessOptional.get();
        synchronized (this){
            List<BmsUserReceCoupon> bmsUserReceCoupons = bmsUserReceCouponService.getBaseDao().findByUserIdAndType(userId,Constants.USER_RECE_FULL_COUPON);
            //判断用户是否领了这家店铺的券
            if(bmsUserReceCoupons != null && bmsUserReceCoupons.size() > 0){
                for(BmsUserReceCoupon bmsUserReceCoupon : bmsUserReceCoupons){
                    if(bmsUserReceCoupon.getBusinessId().intValue() == businessId.intValue()){
                        bmsUserReceCoupon.getBmsFullCoupon().setBmsBusiness(business);
                        bmsUserReceCoupon.getBmsFullCoupon().setEndTime(bmsUserReceCoupon.getExpireTime());
                        return ResultMapHelper.result(ResultCode.CODE_USER_ALREADY_GET_COUPON,ResultMsg.CODE_USER_ALREADY_GET_COUPON,bmsUserReceCoupon);
                    }
                }
            }
            //判断这个用户是否已经领了5张券
            if(bmsUserReceCoupons != null && bmsUserReceCoupons.size() >= Constants.MAX_FULL_COUPON_GET){
                return ResultMapHelper.result(ResultCode.CODE_USER_ALREADY_GET_COUPON_MAX,ResultMsg.CODE_USER_ALREADY_GET_COUPON_MAX);
            }
            BmsUserReceCoupon bmsUserReceCoupon = new BmsUserReceCoupon();
            bmsUserReceCoupon.setType(Constants.USER_RECE_FULL_COUPON);
            bmsUserReceCoupon.setUserId(userId);
            bmsUserReceCoupon.setBusinessId(businessId);
            bmsUserReceCoupon.setFullCouponId(fullCouponId);
            bmsUserReceCoupon.setStatus(Constants.COMMON_FLAG_FALSE_INT);
            bmsUserReceCoupon.setNewTime(new Date());
            bmsUserReceCoupon.setExpireTime(DateTimeUtils.addMonth(bmsUserReceCoupon.getNewTime(),1));
            bmsUserReceCouponService.getBaseDao().save(bmsUserReceCoupon);
            handPostUserRece(bmsUserReceCoupon,business);
            return ResultMapHelper.success(bmsUserReceCoupon,ResultMsg.MSG_GET_SUCCESS);
        }
    }

    private void handPostUserRece(BmsUserReceCoupon bmsUserReceCoupon,BmsBusiness bmsBusiness) {
        Optional<BmsFullCoupon> bmsFullCouponOptional = bmsFullCouponDao.findById(bmsUserReceCoupon.getFullCouponId());
        if(bmsFullCouponOptional.isPresent()){
            bmsUserReceCoupon.setBmsFullCoupon(bmsFullCouponOptional.get());
            bmsUserReceCoupon.getBmsFullCoupon().setBmsBusiness(bmsBusiness);
            bmsUserReceCoupon.getBmsFullCoupon().setEndTime(bmsUserReceCoupon.getExpireTime());
        }
    }


    @Override
    public Map<String, Object> getBusinessFullCoupon_V2(ParamsMap paramsMap) {
        Map<String,Object> resultMap = new HashMap<>();
        Integer businessId = paramsMap.getInteger("businessId");
        Integer pageSize = 5;
        String activityId = paramsMap.getString("activityId");
        List<BmsFullCoupon> bmsFullCoupons = new LinkedList<>();
        //找出推荐满减券
        resultMap.putAll(getNearBusinessFullCoupon(bmsFullCoupons,businessId,activityId,pageSize,paramsMap));
        bmsFullCoupons = (List<BmsFullCoupon>) resultMap.get("fullCoupons");
        if(bmsFullCoupons.size() > 0){
            Set<Integer> businessIds = new HashSet<>();
            for(BmsFullCoupon bmsFullCoupon : bmsFullCoupons){
                businessIds.add(bmsFullCoupon.getBusinessId());
            }
            Map<Integer, BmsBusiness> bmsBusinessMap = bmsBusinessService.findBusinessByIds(businessIds);
            for(BmsFullCoupon bmsFullCoupon : bmsFullCoupons){
                if(bmsBusinessMap.containsKey(bmsFullCoupon.getBusinessId())){
                    bmsFullCoupon.setBmsBusiness(bmsBusinessMap.get(bmsFullCoupon.getBusinessId()));
                }
            }
        }
        resultMap.put("fullCoupons",bmsFullCoupons);
        return ResultMapHelper.success(resultMap, ResultMsg.MSG_GET_SUCCESS);
    }

    @Override
    public List<BmsFullCoupon> findByIds(Set<Integer> bmsFullCouponIds) {
        return bmsFullCouponDao.findByIdIn(bmsFullCouponIds);
    }
}